package com.tsinjie.metadata.java;

import com.tsinjie.metadata.exception.BuildException;
import com.tsinjie.metadata.java.model.JavaClass;
import com.tsinjie.metadata.java.model.JavaProject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.sql.Timestamp;
import java.util.List;

/**
 * Created by LiuXunming on 2015-10-29.
 * JavaProject构建抽象父类
 */
public abstract class AbstractJavaProjectBuilder<Source> implements JavaProjectBuilder {
    protected Logger logger = LoggerFactory.getLogger(getClass());
    /**
     * 表名分隔符，表命名规则 t_module_tableName
     */
    public static final String TABLE_NAME_SPLIT_CHAR = "_";
    /**
     * 包名分隔符
     */
    public static final String PACKAGE_NAME_SPLIT_CHAR = "-";
    /**
     * 点号，用于构造包路径
     */
    public static final String POINT = ".";
    /**
     * 构建数据来源
     */
    protected Source source;
    /**
     * 是否包含模块标识
     */
    protected boolean hasModule = false;

    protected AbstractJavaProjectBuilder(Source source) {
        this.source = source;
    }

    /**
     * 构建对象
     *
     * @return
     */
    public JavaProject build() {
        /**
         * 返回数据信息
         */
        JavaProject javaProject = null;
        logger.debug("JavaProjectBuilder begin : " + new Timestamp(System.currentTimeMillis()));
        try {
            javaProject = javaProject();
            logger.debug("build javaProject success.");
            javaClasses(javaProject);
            logger.debug("build javaClasses success.");
            List<JavaClass> javaClasses = javaProject.getJavaClasses();
            fields(javaClasses);
            logger.debug("build fields success.");
            hibernateRelationship(javaClasses);
            logger.debug("build hibernateRelationship success.");
        } catch (Exception e) {
            throw new BuildException(e);
        } finally {
            afterProcess();
        }
        logger.debug("JavaProjectBuilder end : " + new Timestamp(System.currentTimeMillis()));
        return javaProject;
    }


    /**
     * 构建JavaProject对象
     * {@link com.tsinjie.metadata.java.model.JavaProject}
     *
     * @return JavaProject
     * @throws Exception
     */
    protected abstract JavaProject javaProject() throws Exception;

    /**
     * 构建java类信息列表
     * {@link com.tsinjie.metadata.java.model.JavaClass}
     *
     * @param javaProject
     * @throws Exception
     */
    protected abstract void javaClasses(JavaProject javaProject) throws Exception;

    /**
     * 构建字段信息（包括主字段、外来字段、普通字段）
     * {@link com.tsinjie.metadata.java.model.JavaField}
     *
     * @param javaClasses
     * @throws Exception
     */
    protected abstract void fields(List<JavaClass> javaClasses) throws Exception;

    /**
     * 构建hibernate关系
     * 1、一对一副表（只对应一个主表）
     * 2、一对一主表（可以被多个表引用）
     * 3、一对多
     * 4、多对一
     * 5、多对多
     * {@link com.tsinjie.metadata.java.model.hibernate.OneToOne}
     * {@link com.tsinjie.metadata.java.model.hibernate.OneToMany}
     * {@link com.tsinjie.metadata.java.model.hibernate.ManyToOne}
     * {@link com.tsinjie.metadata.java.model.hibernate.ManyToMany}
     *
     * @param javaClasses
     * @throws Exception
     */
    protected abstract void hibernateRelationship(List<JavaClass> javaClasses) throws Exception;

    /**
     * 分析是否包含模块
     *
     * @return
     */
    protected abstract boolean analysisContainModule();

    /**
     * 手动设置是否包含模块
     *
     * @param hasModule
     */
    public void setHasModule(boolean hasModule) {
        this.hasModule = hasModule;
    }

    /**
     * 构建完成后处理（如：释放资源等操作）
     */
    protected void afterProcess() {

    }

}
